import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Vector;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamConstants;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;

/**
 * Handles the XML reading and writing for the S-R protocol.
 * @author bjorn, kristian
 * 
 */
public class XMLHandler {
	
	private Vector<ServerCommand> commands;

	/**
	 * Creates a new empty XML handler.
	 */
	public XMLHandler() {
		this.commands = new Vector<ServerCommand>();
	}

	// XML reading
	
	/**
	 * Returns the value of the valueName parameter of the i:th ServerCommand.
	 * @param i
	 * @param valueName
	 * @return The value of the parameter.
	 */
	public Integer getValue(Integer i, String valueName) {
		return commands.elementAt(i).getValueOfParameter(valueName);
	}

	/**
	 * Returns the list of server commands in the XML.
	 * @return The command vector of the XMLHandler.
	 */
	public Vector<ServerCommand> getCommand() {
		return commands;
	}

	/**
	 * Gets the name of the i:th server command.
	 * @param i
	 * @return The name of the i:th server command.
	 */
	public String getName(Integer i) {
		return commands.elementAt(i).getName();
	}

	/**
	 * Evaluates if the i:th command is a move command.
	 * @param i
	 * @return True if the i:th command is a move command, false otherwise.
	 */
	public Boolean isMove(Integer i) {
		return commands.elementAt(i).isMove();
	}

	/**
	 * Evaluates if the i:th command is a reboot command.
	 * @param i
	 * @return True if the i:th command is a reboot command, false otherwise.
	 */
	public Boolean isReboot(Integer i) {
		return commands.elementAt(i).isReboot();
	}

	/**
	 * Evaluates if the i:th command is a rotate command.
	 * @param i
	 * @return True if the i:th command is a rotate command, false otherwise.
	 */
	public Boolean isRotate(Integer i) {
		return commands.elementAt(i).isRotate();
	}

	/**
	 * Evaluates if the i:th command is a G2close command.
	 * @param i
	 * @return True if the i:th command is a G2close command, false otherwise.
	 */
	public Boolean isClose(Integer i) {
		return commands.elementAt(i).isClose();
	}
	
	/**
	 * Evaluates if the i:th command is a G2close command.
	 * @param i
	 * @return True if the i:th command is a G2close command, false otherwise.
	 */
	public Boolean isAuto(Integer i) {
		return commands.elementAt(i).isAuto();
	}

	/**
	 * Evaluates if the i:th command is a scan command.
	 * @param i
	 * @return True if the i:th command is a scan command, false otherwise.
	 */
	public Boolean isScan(Integer i) {
		return commands.elementAt(i).isScan();
	}
	
	/**
	 * Initiates the XMLHandler with XML data from xmlString.
	 * @param xmlString
	 * @throws XMLStreamException
	 */
	public void fromXML(String xmlString) throws XMLStreamException {

		if (!xmlString.isEmpty()) {

			XMLStreamReader StreamReader;
			XMLInputFactory InputFactory = XMLInputFactory.newInstance();

			InputStream is = new ByteArrayInputStream(xmlString.getBytes());
			StreamReader = InputFactory.createXMLStreamReader(is);

			String localName = "";
			String value = "";
			Integer next = 0;

			Vector<CommandParameter> tempParam = new Vector<CommandParameter>();

			while (StreamReader.hasNext()) {
				next = StreamReader.next();
				if (next == XMLStreamReader.START_ELEMENT) {
					localName = StreamReader.getLocalName();
					try {
						for (Integer i = 0; i < StreamReader
								.getAttributeCount(); i++) {

							tempParam
									.addElement(new CommandParameter(
											StreamReader.getAttributeName(i)
													.toString(),
											Integer.parseInt(StreamReader
													.getAttributeValue(i))));
						}
						addCommand(new ServerCommand(localName, tempParam));
					} catch (Exception e) {

					}
				}
				tempParam.clear();
			}
		}
	}


	
	// XML construction
	
	/**
	 * Adds the cmd ServerCommand to the XML.
	 * @param cmd
	 */
	public void addCommand(ServerCommand cmd) {
		commands.addElement(cmd);
	}

	/**
	 * Returns a string with the XML data of the XMLHandler, using root element root.
	 * @param root
	 * @return A string containing the XML data representing the data in the XML handler.
	 */
	public String toString(String root) {
		StringBuilder sb = new StringBuilder();
		sb.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
		sb.append("<" + root + ">\n");
		for (int i = 0; i < commands.size(); i++) {
			sb.append("<" + commands.elementAt(i).getName());
			for (Integer j = 0; j < commands.elementAt(i).commandParameterCount(); j++) {
				sb.append(" "
						+ commands.elementAt(i).getCommandParameter(j)
								.getName()
						+ "=\""
						+ commands.elementAt(i).getCommandParameter(j)
								.getValue().toString() + "\"");
			}
			sb.append("/>\n");
		}

		sb.append("</" + root + ">");
		return sb.toString();
	}

	/**
	 * Clears the XMLHandler data.
	 */
	public void clear() {
		commands.clear();
	}

}
